﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CoursePack;
using Heap;

namespace Scheduler
{
    public enum TypeTimeConstraint { regular, morningOff, eveningOff, afternoonOff,dayOff};

    public class TimeConstraint : Constraint
    {

        #region Data
        private TimeSpan m_Start;
        private TimeSpan m_End;
        private DayOfWeek m_Day;
        private TypeTimeConstraint m_Type;
        #endregion

        public TimeConstraint(TimeSpan _Start, TimeSpan _End, DayOfWeek _DayOfWeek)
            : base()
        {
            this.m_Start = _Start;
            this.m_End = _End;
            this.m_Day = _DayOfWeek;
            this.m_Type = TypeTimeConstraint.regular;
        }

        public TimeConstraint(TypeTimeConstraint _Type, DayOfWeek _DayOfWeek)
        {
            this.m_Type = _Type;
            this.m_Day = _DayOfWeek;

            switch (_Type)
            {
                case TypeTimeConstraint.dayOff:
                    this.m_Start = new TimeSpan(8, 45, 0);
                    this.m_End = new TimeSpan( 23, 0, 0);
                    break;
                case TypeTimeConstraint.morningOff:
                    this.m_Start = new TimeSpan(8, 45, 0);
                    this.m_End = new TimeSpan(12, 30, 0);
                    break;
                case TypeTimeConstraint.afternoonOff:
                    this.m_Start = new TimeSpan(12, 30, 0);
                    this.m_End = new TimeSpan(18, 0, 0);
                    break;
                case TypeTimeConstraint.eveningOff:
                    this.m_Start = new TimeSpan(18, 0, 0);
                    this.m_End = new TimeSpan(23, 0, 0);
                    break;
                default:
                    this.m_Start = new TimeSpan(0, 0, 0);
                    this.m_End = new TimeSpan(23, 59, 0);
                    break;
            }

        }


        public Key CheckConstraint(Course _Course)
        {
            CourseKey key = new CourseKey();
            key.Lec = true;
            key.Tut = true;
            key.Lab = true;

            if (this.m_Type == TypeTimeConstraint.dayOff)
            {
                if (_Course.Lecture.DaysOfTheWeek.Contains(this.m_Day))
                {
                    key.Lec = false;
                    if (_Course.HasTutorial)
                        if (_Course.Tutorial.DaysOfTheWeek.Contains(this.m_Day))
                            key.Tut = false;

                    if (_Course.HasLab)
                        if (_Course.Lab.DaysOfTheWeek.Contains(this.m_Day))
                            key.Lab = false;

                    return key;
                }
                
                else
                    return key;
            }

            //Lecture constraint verification
            if (_Course.Lecture.DaysOfTheWeek.Contains(this.m_Day) &&
                ((_Course.Lecture.StartDate.TimeOfDay >= this.m_Start) && (_Course.Lecture.StartDate.TimeOfDay < this.m_End) ||
                ((_Course.Lecture.EndDate.TimeOfDay > this.m_Start) && (_Course.Lecture.EndDate.TimeOfDay < this.m_End))))
            {
                key.Lec = false;
            }

            //Tutorial constraint verification
            if (_Course.HasTutorial)
            {
                if (_Course.Tutorial.DaysOfTheWeek.Contains(this.m_Day) &&
                ((_Course.Tutorial.StartDate.TimeOfDay >= this.m_Start) && (_Course.Tutorial.StartDate.TimeOfDay < this.m_End) ||
                ((_Course.Tutorial.EndDate.TimeOfDay > this.m_Start) && (_Course.Tutorial.EndDate.TimeOfDay <= this.m_End))))
                {
                    key.Tut = false;
                }
            }

            //Lab constraint verification
            if (_Course.HasLab)
            {
                if (_Course.Lab.DaysOfTheWeek.Contains(this.m_Day) &&
                ((_Course.Lab.StartDate.TimeOfDay >= this.m_Start) && (_Course.Lab.StartDate.TimeOfDay < this.m_End) ||
                ((_Course.Lab.EndDate.TimeOfDay > this.m_Start) && (_Course.Lab.EndDate.TimeOfDay <= this.m_End))))
                {
                    key.Lab = false;
                }
            }

            return key;
        }

        #region Accessors
        public TimeSpan StartTime
        {
            get { return this.m_Start; }
        }

        public TimeSpan EndTime
        {
            get { return this.m_End; }
        }

        public DayOfWeek DayOfWeek
        {
            get { return this.m_Day; }
        }
        #endregion
    }
}
